﻿using AdminBase.Common.Helpers;
using AdminBase.Interface;
using AdminBase.Model;
using AdminBase.Model.Entitys;
using AutoMapper;
using Microsoft.Extensions.Options;
using SqlSugar;

namespace AdminBase.Service
{
    /// <summary>
    /// 用户业务类
    /// </summary>
    public class UsersService : IUsersService
    {
        private readonly IMapper _mapper;
        private ISqlSugarClient _db { get; set; }
        private readonly DefaultSettings _defaultSettings;

        /// <summary>
        /// 依赖注入
        /// </summary>
        /// <param name="mapper"></param>
        /// <param name="db"></param>
        /// <param name="defaultSettings"></param>
        public UsersService(IMapper mapper, ISqlSugarClient db, IOptions<DefaultSettings> defaultSettings)
        {
            _mapper = mapper;
            _db = db;
            _defaultSettings = defaultSettings.Value;
        }

        /// <summary>
        /// 更新登陆时间
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task UpdateLoginTimeAsync(long id)
        {
            var entity = _db.Queryable<Users>().First(p => p.ID == id);
            entity.LastLoginDateTime = DateTime.Now;
            await _db.Updateable(entity).ExecuteCommandAsync();
        }

        /// <summary>
        /// 根据id或账号获取单个用户
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userName"></param>
        /// <returns></returns>
        public UsersDto GetUser(long? id = null, string? userName = null)
        {
            if (id != null && id.HasValue)
            {
                return _mapper.Map<UsersDto>(_db.Queryable<Users>().Where(u => u.ID == id).First());
            }
            if (!string.IsNullOrWhiteSpace(userName))
            {
                return _mapper.Map<UsersDto>(_db.Queryable<Users>().Where(u => u.UserName == userName).First());
            }
            return null;
        }

        /// <summary>
        /// 判断用户是否已存在
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public bool Exists(string userName)
        {
            return _db.Queryable<Users>().Any(u => u.UserName == userName);
        }

        /// <summary>
        /// 获取用户相关信息：角色、权限、部门、头像等
        /// </summary>
        /// <param name="id">id</param>
        /// <returns></returns>
        public UsersDto GetUserInfo(long id)
        {
            var sugarQueryable = _db.Queryable<Users>().First(u => u.ID == id);
            if (sugarQueryable == null)
            {
                return new UsersDto();
            }
            var dto = _mapper.Map<UsersDto>(sugarQueryable);
            // 头像
            if (!string.IsNullOrWhiteSpace(dto.Avatar))
            {
                var avatar = _db.Queryable<Files>().First(p => p.FileID == dto.Avatar);
                if (avatar != null)
                {
                    dto.AvatarUrl = avatar.FilePath;
                }
            }
            // 部门
            if (dto.DepartmentID.HasValue)
            {
                dto.DepartmentName = _db.Queryable<Departments>()
                    .Where(d => d.ID == dto.DepartmentID.Value).Select(d => d.Name).First();
            }
            // 获取角色
            var roles = GetRolesByUserId(dto.ID);
            if (roles.Any())
            {
                dto.Roles = roles.Select(u => u.ID).ToList();
                dto.RolesName = roles.Select(u => u.Name).ToList();
            }
            if (dto.IsSuperUser && !dto.RolesName.Contains("admin"))
            {
                dto.RolesName.Add("admin");
            }
            // 获取权限
            var roleIDs = _db.Queryable<UsersRoles>().Where(u => u.UserID == dto.ID).Select(u => u.RoleID).ToList();
            var permissionIDs = _db.Queryable<RolesPermissions>().Where(p => roleIDs.Contains(p.RoleID)).Select(p => p.PermissionID).ToList();
            var permissions = _db.Queryable<Permissions>().In(permissionIDs)
                .Select(p => new PermissionsDto
                {
                    ID = p.ID,
                    Sign = p.Sign
                })
                .ToList();
            if (permissions.Any())
            {
                dto.Permissions = permissions.Select(p => p.Sign).Distinct().ToList();
            }
            if ((dto.IsSuperUser || dto.RolesName.Contains("admin")) && !dto.Permissions.Contains("admin"))
            {
                dto.Permissions.Add("admin");
            }

            return dto;
        }

        /// <summary>
        /// 获取用户列表
        /// </summary>
        /// <param name="queryParam">查询参数</param>
        /// <param name="pageBase">分页查询</param>
        /// <returns></returns>
        public PageInfo GetUsers(UsersQueryParam queryParam, PageBase pageBase)
        {
            var exp = _db.Queryable<Users>();
            // 关键词查询
            if (!string.IsNullOrWhiteSpace(queryParam.KeyWord))
            {
                exp.Where(u =>
                (u.UserName != null && u.UserName.Contains(queryParam.KeyWord)) ||
                (u.FullName != null && u.FullName.Contains(queryParam.KeyWord)) ||
                (u.Mobile != null && u.Mobile.Contains(queryParam.KeyWord)) ||
                (u.Email != null && u.Email.Contains(queryParam.KeyWord)));
            }
            // 部门
            if (queryParam.DepartmentID.HasValue)
            {
                List<long> deptIDs = new List<long>();
                List<long> pids = new List<long>() { queryParam.DepartmentID.Value };
                GetDeptChildrenIDs(pids, ref deptIDs);
                exp.Where(u => u.DepartmentID != null && deptIDs.Contains(u.DepartmentID.Value));
            }
            // 状态
            if (queryParam.IsActive.HasValue)
            {
                exp.Where(u => u.IsActive == queryParam.IsActive);
            }
            // 排序分页
            PageInfo pageInfo = PagedHelper.GetPageData(exp, pageBase);
            var list= pageInfo.Data as List<Users>;
            List<UsersDto> usersDtoList = new List<UsersDto>();
            // 角色名、部门名
            list.ForEach(user =>
            {
                UsersDto usersDto = _mapper.Map<UsersDto>(user);
                // 获取角色
                var roles = GetRolesByUserId(user.ID);
                if (roles.Any())
                {
                    usersDto.Roles = roles.Select(u => u.ID).ToList();
                    usersDto.RolesName = roles.Select(u => u.Name).ToList();
                }
                if (user.DepartmentID.HasValue)
                {
                    usersDto.DepartmentName = _db.Queryable<Departments>()
                        .Where(d => d.ID == user.DepartmentID.Value).Select(d => d.Name).First();
                }
                usersDtoList.Add(usersDto);
            });
            // 分页数据信息
            pageInfo.Data = usersDtoList;
            return pageInfo;
        }

        /// <summary>
        /// 根据部门ID获取子级ID列表
        /// </summary>
        /// <param name="ID"></param>
        /// <returns></returns>
        private void GetDeptChildrenIDs(List<long> pids, ref List<long> ids)
        {
            ids.AddRange(pids);
            // 获取所有子级ID
            var childIds = _db.Queryable<Departments>()
                               .Where(p => p.ParentID != null && pids.Contains(p.ParentID.Value))
                               .Select(p => p.ID)
                               .ToList();
            if (childIds.Any())
            {
                // 递归获取子级
                GetDeptChildrenIDs(childIds, ref ids);
            }
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public bool Add(UsersDto input)
        {
            input.Salt = PasswordHelper.GenerateSalt();
            input.PassWord = PasswordHelper.HashPassword(_defaultSettings.Password, input.Salt);
            input.IsActive = true;
            input = EntityHelper.SetAddValues(input);
            var entity = _mapper.Map(input, new Users());
            // 添加用户
            var userID = _db.Insertable(entity).ExecuteReturnIdentity();
            // 添加角色
            if (input.Roles.Any())
            {
                List<UsersRoles> usersRoles = new List<UsersRoles>();
                input.Roles.ForEach(r =>
                {
                    usersRoles.Add(new UsersRoles()
                    {
                        UserID = userID,
                        RoleID = r
                    });
                });
                if (usersRoles.Any())
                {
                    _db.Insertable(usersRoles).ExecuteCommand();
                }
            }
            return true;
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="input"></param>
        /// <param name="info">修改个人中心信息</param>
        /// <returns></returns>
        public bool Edit(UsersDto input, bool info = false)
        {
            // 更新user
            var entity = _db.Queryable<Users>().First(p => p.ID == input.ID);
            entity = _mapper.Map(input, entity);
            entity = EntityHelper.SetEditValues(entity);
            _db.Updateable(entity).ExecuteCommand();

            // 如果只是修改个人中心信息，到此结束
            if (info)
            {
                return true;
            }

            // 更新角色，先删除旧的再添加
            _db.Deleteable<UsersRoles>().Where(u => u.UserID == input.ID).ExecuteCommand();
            if (input.Roles.Any())
            {
                List<UsersRoles> usersRoles = new List<UsersRoles>();
                input.Roles.ForEach(r =>
                {
                    usersRoles.Add(new UsersRoles()
                    {
                        UserID = input.ID,
                        RoleID = r
                    });
                });
                if (usersRoles.Any())
                {
                    _db.Insertable(usersRoles).ExecuteCommand();
                }
            }
            return true;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool Del(long id)
        {
            var info = _db.Queryable<Users>().First(p => p.ID == id);
            _db.Deleteable(info).ExecuteCommand();
            // 删除角色
            _db.Deleteable<UsersRoles>().Where(u => u.UserID == id).ExecuteCommand();
            return true;
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public bool BatchDel(List<long> ids)
        {
            // 删除用户
            _db.Deleteable<Users>().In(ids).ExecuteCommand();
            // 删除角色
            _db.Deleteable<UsersRoles>().Where(u => ids.Contains(u.UserID)).ExecuteCommand();
            return true;
        }

        /// <summary>
        /// 根据userid获取角色
        /// </summary>
        /// <param name="uid"></param>
        /// <returns></returns>
        public List<Roles> GetRolesByUserId(long uid)
        {
            var roleIDs = _db.Queryable<UsersRoles>().Where(p => p.UserID == uid).Select(r => r.RoleID).Distinct().ToList();
            var roles = _db.Queryable<Roles>().Where(p => roleIDs.Contains(p.ID)).ToList();
            return roles;
        }

        /// <summary>
        /// 修改激活状态
        /// </summary>
        /// <param name="users"></param>
        /// <returns></returns>
        public bool UpdateActive(Users users)
        {
            var entity = _db.Queryable<Users>().Where(u => u.ID == users.ID).First();
            entity.IsActive = users.IsActive;
            return _db.Updateable(entity).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 设置密码
        /// </summary>
        /// <param name="passwordDto"></param>
        /// <returns></returns>
        public bool SetPassword(PasswordDto passwordDto)
        {
            // 更新user
            var entity = _db.Queryable<Users>().First(p => p.ID == passwordDto.ID);
            if (string.IsNullOrWhiteSpace(entity.Salt))
            {
                entity.Salt = PasswordHelper.GenerateSalt();
            }
            if (string.IsNullOrWhiteSpace(passwordDto.ConfirmPassword))
            {
                passwordDto.ConfirmPassword = _defaultSettings.Password;
            }
            entity.PassWord = PasswordHelper.HashPassword(passwordDto.ConfirmPassword, entity.Salt);

            entity = EntityHelper.SetEditValues(entity);
            return _db.Updateable(entity).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 设置头像
        /// </summary>
        /// <param name="userName">账号</param>
        /// <param name="fileID">文件ID</param>
        /// <returns></returns>
        public bool SetAvatar(string userName, string fileID)
        {
            var entity = _db.Queryable<Users>().Where(u => u.UserName == userName).First();
            if (entity != null)
            {
                entity.Avatar = fileID;
                entity.UpdateDateTime = DateTime.Now;
                return _db.Updateable(entity).ExecuteCommand() > 0;
            }
            return false;
        }
    }
}
